﻿/*+===================================================================
File:      EnemyShelter.cpp

Summary:   Định nghĩa các phương thức của CEnemyShelter.
===================================================================+*/

#include "EnemyShelter.h"
#include "PlayState.h"
#include "Explosion.h"

// Các trạng thái của EnemySniper.
#define STATUS_HIDE			0
#define STATUS_RISING		1
#define STATUS_SIT			2
#define STATUS_HIDING		3
#define STATUS_DIE			4

#define MAX_BULLETS			1

// Mảng Sprite animation.
int spriteID[4] =
{
	ID_SPRITE_ENEMY_SHELTER_HIDE,
	ID_SPRITE_ENEMY_SHELTER_RISE,
	ID_SPRITE_ENEMY_SHELTER_SIT,
	ID_SPRITE_ENEMY_SHELTER_RISE,
};

CEnemyShelter::CEnemyShelter(CBill* bill, D3DXVECTOR2 pos, int id, int typeId)
: CMoveableObject(pos, id, typeId)
{
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_HIDE);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_RISE);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_SIT);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_STAND);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_STAND_FIRE);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_BOT);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_BOT_FIRE);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_ENEMY_SHELTER_DIE);
	m_bill = bill;
	m_nStatus = STATUS_HIDE;
	m_pSprite = m_pResourceManager->GetSprite(spriteID[m_nStatus]);
	m_bIsRight = false;
	m_pGun = new CGun(ID_ENEMY_SMALL_WHITE_BULLET, MAX_BULLETS, 1);
	m_v.y = 200.0f;
	m_box.width = 52;
	m_box.height = 32;
}

CEnemyShelter::~CEnemyShelter()
{
	if (m_pGun)
		delete m_pGun;
	if (m_bill)
		delete m_bill;
}

void CEnemyShelter::Update(float timeFrame)
{
	if (!m_bIsLive)
	{
		// Tính toán hiệu ứng khi enemy bị trúng đạn, Enemy
		// sẽ bị nảy lên đến một thời gian nào đó và nổ.
		if (m_timeDie > 0)
		{
			m_timeDie -= timeFrame;
			m_pos.y += m_v.y * timeFrame;
		}
		else if (m_timeDie < 0)
		{
			m_timeDie = 0.0f;
			Kill();
		}

		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_ENEMY_SHELTER_DIE);
		return;
	}


	m_pSprite->Update(timeFrame);

	if (m_fTimeChange > 0)
	{
		m_fTimeChange -= timeFrame;
	}
	else
	{
		m_nStatus = (m_nStatus + 1) % 4;

		// Điều chỉnh thời gian chuyển trạng thái.
		switch (m_nStatus)
		{
			case STATUS_HIDE:
				m_fTimeChange = 1.67f;
				break;
			case STATUS_RISING:
			case STATUS_HIDING:
				m_fTimeChange = 0.1f;
				break;
			case STATUS_SIT:
				m_fTimeChange = 2.5f;
				break;
		}
		
		m_pSprite = m_pResourceManager->GetSprite(spriteID[m_nStatus]);
	}

	D3DXVECTOR2 billPos = m_bill->GetPos();

	// Tính toán góc của bill so với vị trí của EnemyShelter.
	// Dời tọa độ gốc(0, 0) về tọa độ của EnemyShelter để tính góc.
	float angle = atan2(billPos.y - m_pos.y, billPos.x - m_pos.x) * 180 / PI;

	// Nếu EnemyShelter đang đứng mới tính hành cập nhật hướng bắn và hướng sprite theo Bill.
	if (m_nStatus == STATUS_SIT)
	{
		if ((0 <= angle &&  angle < 90) || (-90 <= angle &&  angle < 0))
		{
			m_pGun->SetBulletAngle(0);
			m_bIsRight = true;
		}

		else
		{
			m_pGun->SetBulletAngle(180);
			m_bIsRight = false;
		}

		// Vừa đứng lên là bắn sau đó phải đợi đến lượt 
		// đứng tiếp theo mới có thể bắn tiếp.
		if (m_fTimeChange > 2.48f)
		{
			// Tính toán vị trí đạn để bắn.
			D3DXVECTOR2 bulletPos;
			bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f;
			bulletPos.y = m_pos.y - 10.0f;
			if (m_bIsRight)
				bulletPos.x = m_pos.x + (m_pos.x - bulletPos.x);

			m_pGun->Fire(bulletPos);
		}
	}
	
	UpdateBox(timeFrame);
}

void CEnemyShelter::UpdateBox(float timeFrame)
{
	m_box.x = m_pos.x - m_box.width / 2.0f;
	m_box.y = m_pos.y;
	m_box.vX = m_v.x;
	m_box.vY = m_v.y;
}

void CEnemyShelter::UpdateCollision(vector<CGameObject*> vecGameObjs, float timeFrame)
{
	if (!m_bIsLive)
		return;

	float timeCollision = timeFrame;
	CGameObject* objCollision = NULL; // Đối tượng va chạm sớm nhất.
	float normalx = 0.0f, normaly = 0.0f;

	// Xử lí va chạm với đạn của Bill
	for (int i = 0; i < CPlayState::s_billBullets.size(); i++)
	{
		if (CPlayState::s_billBullets[i]->IsLive())
		{
			float t = CheckCollision(CPlayState::s_billBullets[i], normalx, normaly, timeFrame);

			if (t < timeFrame && t < timeCollision)
			{
				// Tìm đối tượng và thời gian va chạm sớm nhất.
				timeCollision = t;
				objCollision = CPlayState::s_billBullets[i];
			}
		}
	}

	// Xử lí va chạm
	if (objCollision != NULL && m_nStatus == STATUS_SIT)
	{
		m_timeDie = 0.2f;
		m_nStatus = STATUS_DIE;
		m_bIsLive = false;

		objCollision->Kill();
	}
}

void CEnemyShelter::Draw()
{
	if (!m_bIsLive && m_timeDie == 0.0f)
		return;
	D3DXVECTOR2 pos = CViewport::GetInstance()->TransformMatrix(m_pos);
	if (!m_bIsRight)
		m_pSprite->Draw(pos);
	else
		m_pSprite->DrawFlipX(pos);
	
}

bool CEnemyShelter::Kill()
{
	CExplosion* explosion = new CExplosion(m_pos, 0, ID_ENEMY_EXPLOSION);
	CPlayState::s_objsOutSideQuadTree.push_back(explosion);
	g_nScore += 100;
	return true;
}